3D Graphics Programming with QuickDraw 3D 1.5.4
Previous | QD3D Book | Overview | Chapter Contents | Next |
This section contains information that is useful if you are implementing a drawing engine to support hardware that is based on an OpenGL rasterization model. It describes special considerations for handling transparency and texture mapping.
QuickDraw 3D RAVE supports three transparency models: the premultiplied, interpolated, and OpenGL transparency models. Support for the OpenGL transparency model (indicated by the kQABlend_OpenGL constant) should be automatic for hardware that is based on the OpenGL rasterization model. The other two models, indicated by the kQABlend_PreMultiply and kQABlend_Interpolate constants) may require emulation by your drawing engine.
For example, consider the premultiplied blending function, specified by these equations:
(Here, the factors s , s , s , and s represent the alpha, red, green and blue components of a source pixel; the factors d , d , d , and d represent the alpha, red, green and blue components of a destination pixel.)
A complete description of how transparent objects are blended together with each of these models is provided in "Blending Operations" .
OpenGL directly supports the premultiplied transparency blending function (and the interpolated transparency blending function) for the RGB components only. In other words, the alpha channel component (which is the same for both blending operations) cannot be directly implemented in OpenGL-compliant hardware. It is possible, however, to emulate these two transparency modes on OpenGL hardware, using several different methods. You can blend the RGB values only, or you can blend the ARGB values using a multipass algorithm. Which of these emulations you use depends on whether your drawing engine is associated with a frame buffer that stores an alpha channel or not.
If your drawing engine is associated with a frame buffer that doesn't store an alpha channel value, you can implement the premultiplied and interpolated blending functions by simply ignoring the alpha channel component. These functions are then equivalent to OpenGL blending modes. The premulitplied blending function, with its alpha channel ignored, can be emulated by this function:
gBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Similarly, the interpolated blending function, with its alpha channel ignored, can be emulated by this function:
gBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
A drawing engine that uses this method of emulating the QuickDraw 3D RAVE blending functions on OpenGL hardware should not set the kQAOptional_BlendAlpha flag of the kQAGestalt_OptionalFeatures selector to the QAEngineGestalt function.
To achieve a more complete blending, you can have your drawing engine rasterize each transparent object more than once, altering in each pass the blending mode, object alpha channel, and buffer write masks. The first pass should perform RGB blending. Accordingly, you should disable writing any alpha channel or z buffer data during this pass.
/*first pass*/
glColorMask(TRUE, TRUE, TRUE, FALSE); /*disable alpha channel*/
glDepthMask(FALSE); /*disable Z buffer*/
if (premultpliedTransparency)
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*render the object here*/
On the second pass, you should set the frame buffer alpha channel value to (1- a s )(1- a d ). To do this, you need to render the object again, with a different alpha value, as follows:
/*second pass*/
glColorMask(FALSE, FALSE, FALSE, TRUE); /*enable alpha channel*/
glDepthMask(FALSE); /*disable Z buffer*/
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
/*render the object with alpha replaced with 1-a*/
Finally, the third pass should replace the value in the alpha channel with the final value 1-((1- a s )(1- a d )). To do this, you need to render the object again, with its alpha value set to 1, as follows:
/*third pass*/
glColorMask(FALSE, FALSE, FALSE, TRUE); /*enable alpha channel*/
glDepthMask(TRUE); /*enable Z buffer*/
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
/*render the object with alpha replaced with 1*/
After the third pass, the frame buffer contains the correctly blended object.
QuickDraw 3D RAVE supports several texture mapping operations, which are controlled by the flags in the kQATag_TextureOp state variable. Currently these flags are defined:
#define kQATextureOp_Modulate (1 << 0)
#define kQATextureOp_Highlight (1 << 1)
#define kQATextureOp_Decal (1 << 2)
#define kQATextureOp_Shrink (1 << 3)
A complete description of texture mapping operations is provided in "Texture Operations" .
To support the kQATextureOp_Modulate mode on an OpenGL-compliant rasterizer, you can use the GL_MODULATE mode, where the kd_r , kd_g , and kd_b fields of a texture vertex specify the modulating color. Note, however, that GL_MODULATE does not allow these color values to be greater than 1.0, whereas QuickDraw 3D RAVE does allow them to be greater than 1.0. Values greater than 1.0 can provide improved image realism, and new hardware should support them. A more reasonable maximum modulation amplitude is 2.0.
You can support the kQATextureOp_Highlight mode by performing two rendering passes. The first pass should render the texture-mapped object (possibly also with modulation, as just described), and the second pass should add the specular highlight value.
/*first pass*/
glDepthMask(FALSE); /*disable Z buffer*/
/*render the texture-mapped object here*/
/*second pass*/
glDepthMask(TRUE); /*enable Z buffer*/
glBlendFunc(GL_ONE, GL_ONE); /*add highlight color*/
/*render the highlight color as a Gouraud-shaded object here*/
On the second pass, you should render the highlight color, using the ks_r , ks_g , and ks_b fields of a texture vertex, as a Gouraud-shaded object.
If the kQATextureOp_Modulate flag is clear (that is, is no texture map color modulation is to be performed), you can support the kQATextureOp_Decal mode using the OpenGL GL_DECAL mode. If, in addition, the kQATextureOp_Highlight flag is set, you need to perform two rendering passes, as just described.
There is currently no known method of accurately rendering to OpenGL-compliant hardware when both the kQATextureOp_Decal and the kQATextureOp_Modulate flags are set. You should determine the best method of implementing this mode correctly on your hardware. If your hardware cannot handle both modes at once, you should ignore the kQATextureOp_Modulate mode whenever kQATextureOp_Decal is set.
Previous | QD3D Book | Overview | Chapter Contents | Next |